<script setup name="ModelSaveAndApplication">
import { ref, computed, watch } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Download, Upload } from '@element-plus/icons-vue'
import {
	postModelSavePlk,
	postModelUse,
} from '@/api/product/machineLearning.js'

const props = defineProps({
	modelValue: {
		type: Object,
		default: () => ({
			fileName: '',
			algorithm: '',
			algorithmName: '',
			formData: {},
			targetFeatureTable: [],
		}),
	},
})

const emit = defineEmits(['update:modelValue'])

// 加载状态
const isModelSaving = ref(false)
const isModelApplying = ref(false)

// 模型应用的输入数据
const applicationData = ref([])

// 计算X列数据（改为数组格式）
const xColumns = computed(() => {
	const xFeatures =
		props.modelValue.targetFeatureTable
			?.filter((item) => item.isFeature === true)
			?.map((item) => item.name) || []

	// 返回完整的数组，而不是只取第一个
	return xFeatures
})

// 计算Y列
const yColumn = computed(() => {
	return (
		props.modelValue.targetFeatureTable?.find((item) => item.isTarget === true)
			?.name || ''
	)
})

// 监听X列变化，初始化应用数据数组
watch(
	xColumns,
	(newXColumns) => {
		if (newXColumns.length > 0) {
			applicationData.value = new Array(newXColumns.length).fill('')
		}
	},
	{ immediate: true }
)

// 文件下载工具函数
const downloadFile = (blob, filename) => {
	const url = window.URL.createObjectURL(blob)
	const link = document.createElement('a')
	link.href = url
	link.download = filename
	document.body.appendChild(link)
	link.click()
	document.body.removeChild(link)
	window.URL.revokeObjectURL(url)
}

// base64 转 blob 工具函数
const base64ToBlob = (base64Data) => {
	const parts = base64Data.split(',')
	const contentType = parts[0].match(/:(.*?);/)[1]
	const raw = window.atob(parts[1])
	const rawLength = raw.length
	const uInt8Array = new Uint8Array(rawLength)

	for (let i = 0; i < rawLength; ++i) {
		uInt8Array[i] = raw.charCodeAt(i)
	}

	return new Blob([uInt8Array], { type: contentType })
}

// 模型保存
const handleModelSave = async () => {
	try {
		isModelSaving.value = true

		const params = {
			best_params: props.modelValue.formData,
			x: xColumns.value, // 改为数组格式
			y: yColumn.value,
			algorithm: props.modelValue.algorithm,
			file_name: props.modelValue.fileName,
		}

		console.log('模型保存参数:', params)

		const response = await postModelSavePlk(params)
		console.log('模型保存响应:', response)

		if (response && response.code === 200) {
			// 如果返回的是文件流，触发下载
			if (response.data) {
				try {
					// 根据实际情况处理文件下载
					// 如果是 blob 数据，直接下载
					if (response.data instanceof Blob) {
						downloadFile(
							response.data,
							`${props.modelValue.modelName}_model_${props.modelValue.algorithmName}_${Date.now()}.pkl`
						)
					} else if (
						typeof response.data === 'string' &&
						response.data.startsWith('data:')
					) {
						// 如果是 base64 数据，转换为 blob 后下载
						const blob = base64ToBlob(response.data)
						downloadFile(
							blob,
							`${props.modelValue.modelName}_model_${props.modelValue.algorithmName}_${Date.now()}.pkl`
						)
					} else {
						// 其他情况，尝试转换为 blob
						const blob = new Blob([JSON.stringify(response.data)], {
							type: 'application/octet-stream',
						})
						downloadFile(
							blob,
							`model_${props.modelValue.algorithm}_${Date.now()}.pkl`
						)
					}
					ElMessage.success('模型保存成功！文件已开始下载')
				} catch (error) {
					console.error('文件下载处理错误:', error)
					ElMessage.success('模型保存成功！')
				}
			} else {
				ElMessage.success('模型保存成功！')
			}
		} else {
			ElMessage.error('模型保存失败')
		}
	} catch (error) {
		console.error('模型保存错误:', error)
		ElMessage.error('模型保存时发生错误')
	} finally {
		isModelSaving.value = false
	}
}

// 模型应用
const handleModelApplication = async () => {
	// 验证输入数据
	if (
		applicationData.value.some(
			(val) => val === '' || val === null || val === undefined
		)
	) {
		ElMessage.warning('请填写完整的输入数据')
		return
	}

	// 转换为整型数组
	const dataArray = applicationData.value.map((val) => {
		const num = parseInt(val)
		if (isNaN(num)) {
			throw new Error(`输入值 "${val}" 不是有效的整数`)
		}
		return num
	})

	try {
		isModelApplying.value = true

		const params = {
			best_params: props.modelValue.formData,
			x: xColumns.value, // 改为数组格式
			y: yColumn.value,
			algorithm: props.modelValue.algorithm,
			data: dataArray,
			file_name: props.modelValue.fileName,
		}

		console.log('模型应用参数:', params)

		const response = await postModelUse(params)
		console.log('模型应用响应:', response)

		if (response && response.code === 200) {
			ElMessage.success('模型应用成功！')
			// TODO: 根据实际返回结果展示预测结果
		} else {
			ElMessage.error('模型应用失败')
		}
	} catch (error) {
		console.error('模型应用错误:', error)
		if (error.message.includes('不是有效的整数')) {
			ElMessage.error(error.message)
		} else {
			ElMessage.error('模型应用时发生错误')
		}
	} finally {
		isModelApplying.value = false
	}
}

// 验证方法（供父组件调用）
const verification = async () => {
	// 第六步目前没有必须验证的内容，直接返回true
	return true
}

// 暴露方法给父组件
defineExpose({
	verification,
})
</script>

<template>
	<div class="component ModelSaveAndApplication">
		<div class="component-header">
			<div class="component-header-title">模型保存与应用</div>
		</div>

		<div class="content">
			<!-- 模型信息展示 -->
			<div class="model-info">
				<h3>当前模型信息</h3>
				<el-descriptions :column="2" border>
					<el-descriptions-item label="算法">
						{{ props.modelValue.algorithmName || '未选择' }}
					</el-descriptions-item>
					<el-descriptions-item label="文件名">
						{{ props.modelValue.originalName || '未上传' }}
					</el-descriptions-item>
					<el-descriptions-item label="目标列">
						{{ yColumn || '未选择' }}
					</el-descriptions-item>
					<el-descriptions-item label="特征列">
						{{ xColumns.join(', ') || '未选择' }}
					</el-descriptions-item>
				</el-descriptions>
			</div>

			<!-- 模型保存 -->
			<div class="model-save">
				<h3>模型保存</h3>
				<p class="description">
					将训练好的模型保存为 .pkl 文件，可供后续使用。
				</p>
				<el-button
					type="primary"
					:icon="Download"
					:loading="isModelSaving"
					@click="handleModelSave"
					size="large"
				>
					{{ isModelSaving ? '保存中...' : '保存模型' }}
				</el-button>
			</div>

			<!-- 模型应用 -->
			<div class="model-application" v-if="false">
				<h3>模型应用</h3>
				<p class="description">
					输入特征值进行预测。当前需要输入 {{ xColumns.length }} 个特征值：{{
						xColumns.join(', ')
					}}
				</p>

				<div class="input-section" v-if="xColumns.length > 0">
					<el-form label-width="120px">
						<el-form-item
							v-for="(column, index) in xColumns"
							:key="column"
							:label="`${column}:`"
						>
							<el-input
								v-model="applicationData[index]"
								type="number"
								:placeholder="`请输入${column}的值（整数）`"
								:disabled="isModelApplying"
							/>
						</el-form-item>
					</el-form>

					<el-button
						type="success"
						:icon="Upload"
						:loading="isModelApplying"
						@click="handleModelApplication"
						size="large"
						:disabled="!xColumns.length"
					>
						{{ isModelApplying ? '预测中...' : '开始预测' }}
					</el-button>
				</div>

				<el-empty v-else description="请先完成前面的步骤选择特征列" />
			</div>
		</div>
	</div>
</template>

<style scoped lang="scss">
.ModelSaveAndApplication {
	.content {
		padding: 20px;
		max-width: 1200px;
		margin: 0 auto;

		h3 {
			margin-bottom: 16px;
			color: var(--el-text-color-primary);
			font-weight: 600;
			font-size: 18px;
		}

		.description {
			margin-bottom: 16px;
			color: var(--el-text-color-regular);
			line-height: 1.6;
		}

		.model-info {
			margin-bottom: 32px;
			padding: 20px;
			background: var(--el-fill-color-lighter);
			border-radius: 8px;
		}

		.model-save {
			margin-bottom: 32px;
			padding: 20px;
			border: 1px solid var(--el-border-color);
			border-radius: 8px;

			.el-button {
				margin-top: 8px;
			}
		}

		.model-application {
			padding: 20px;
			border: 1px solid var(--el-border-color);
			border-radius: 8px;

			.input-section {
				.el-form {
					margin-bottom: 20px;

					.el-form-item {
						margin-bottom: 16px;
					}
				}
			}
		}
	}
}
</style>
